package controller

import (
	"fmt"
	"net/http"
	"time"

	"github.com/labstack/echo"

	"gopkg.in/mgo.v2/bson"

	"m-project-admin/app/entity"
	"m-project-admin/app/manager"
	"m-project-admin/app/model"
	"m-project-admin/app/utils"
	"strconv"
	"strings"
)

// AddAccount
func AddAccount(c echo.Context) error {
	loginAdminInfo := manager.GetLoginAdminInfo(&c)

	data := make(map[string]interface{})
	data["loginAdminInfo"] = loginAdminInfo
	data["business_line_list"] = model.BusinessList
	data["env_desc"] = utils.GetEnvDesc()
	return c.Render(http.StatusOK, "add_account.html", data)
}

// do add Account
func DoAddAccount(c echo.Context) error {
	name := c.FormValue("name")
	if name == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请填写姓名"})
	}

	account := c.FormValue("account")
	if account == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请填写账号"})
	}

	password := c.FormValue("password")
	if password == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请填写密码"})
	}

	photo := c.FormValue("photo")
	isSuper, _ := strconv.Atoi(c.FormValue("is_super"))
	department, _ := strconv.Atoi(c.FormValue("department"))
	status, _ := strconv.Atoi(c.FormValue("status"))

	params, _ := c.FormParams()

	var businessLines []string
	if tmp, ok := params["business_line[]"]; !ok {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择业务线"})
	} else {
		businessLines = tmp
	}

	// 判断是否存在这个账号
	exRole, err := manager.GetAccountByAccount(account)
	if exRole.Id.Hex() != "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "该账号已存在"})
	}

	tmpPwd := utils.Sha1s([]byte(password))

	accountObj := model.Account{
		Id:            bson.NewObjectId(),
		Name:          name,
		Account:       account,
		Password:      tmpPwd,
		Photo:         photo,
		Is_Super:      isSuper,
		Department:    department,
		BusinessLines: businessLines,
		Status:        status,
		Adminid:       manager.GetCurrentAdminId(&c),
		Create_time:   time.Now().Unix(),
		Update_time:   time.Now().Unix(),
	}

	_, err = manager.SaveAccount(accountObj)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// UpdateAccount
func UpdateAccount(c echo.Context) error {
	loginAdminInfo := manager.GetLoginAdminInfo(&c)

	id := c.QueryParam("id")
	if id == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞请选择要修改的账号😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	// 查询账号信息
	accountObj, _ := manager.GetAccountById(id)
	if accountObj.Id.Hex() == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞要修改的账号数据不存在😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	// 渲染结果到模板
	data := make(map[string]interface{})
	data["accountInfo"] = formatAccount(accountObj)
	data["loginAdminInfo"] = loginAdminInfo
	data["env_desc"] = utils.GetEnvDesc()
	return c.Render(http.StatusOK, "update_account.html", data)
}

// DoUpdateAccount
func DoUpdateAccount(c echo.Context) error {
	id := c.FormValue("id")
	if id == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要修改的账号"})
	}

	name := c.FormValue("name")
	if name == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请填写姓名"})
	}

	account := c.FormValue("account")
	if account == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请填写账号"})
	}

	photo := c.FormValue("photo")
	isSuper, _ := strconv.Atoi(c.FormValue("is_super"))
	department, _ := strconv.Atoi(c.FormValue("department"))
	status, _ := strconv.Atoi(c.FormValue("status"))

	password := c.FormValue("password")

	params, _ := c.FormParams()

	var businessLines []string
	if tmp, ok := params["business_line[]"]; !ok {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择业务线"})
	} else {
		businessLines = tmp
	}

	// 检查角色是否重复
	exAccountItem, _ := manager.GetAccountByAccount(account)
	if (exAccountItem.Id.Hex() != "") && (exAccountItem.Id.Hex() != id) {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "该账号已存在"})
	}

	accountObj := make(map[string]interface{})
	accountObj["name"] = name
	accountObj["account"] = account
	accountObj["photo"] = photo
	accountObj["is_super"] = isSuper
	accountObj["department"] = department
	accountObj["business_lines"] = businessLines
	accountObj["status"] = status
	accountObj["update_time"] = time.Now().Unix()

	if password != "" {
		tmpPwd := utils.Sha1s([]byte(password))
		accountObj["password"] = tmpPwd
	}

	_, err := manager.UpdateAccount(id, accountObj)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// UpdateAccountApp
func UpdateAccountApp(c echo.Context) error {
	loginAdminInfo := manager.GetLoginAdminInfo(&c)

	id := c.QueryParam("id")
	if id == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞请选择要编辑的账号😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	// 查询账号信息
	accountObj, _ := manager.GetAccountById(id)
	if accountObj.Id.Hex() == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞要修改的账号数据不存在😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	accountApps := getApps(accountObj)

	// 渲染结果到模板
	data := make(map[string]interface{})
	data["accountInfo"] = formatAccount(accountObj)
	data["account_apps"] = accountApps
	data["loginAdminInfo"] = loginAdminInfo
	data["env_desc"] = utils.GetEnvDesc()

	return c.Render(http.StatusOK, "update_account_apps.html", data)
}

func DoUpdateAccountApp(c echo.Context) error {
	dataid := c.FormValue("id")
	if dataid == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要操作的账号"})
	}

	appids := strings.TrimSpace(c.FormValue("appids"))

	appidsArray := make([]string, 0)
	if appids != "" {
		appidsArray = strings.Split(appids, ",")
	}

	account := make(map[string]interface{})
	account["apps"] = appidsArray
	account["update_time"] = time.Now().Unix()

	_, err := manager.UpdateAccount(dataid, account)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// UpdateAccountRole
func UpdateAccountRole(c echo.Context) error {
	loginAdminInfo := manager.GetLoginAdminInfo(&c)

	id := c.QueryParam("id")
	if id == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞请选择要编辑的账号😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	// 查询账号信息
	accountObj, _ := manager.GetAccountById(id)
	if accountObj.Id.Hex() == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞要修改的账号数据不存在😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	accountRoles := getRoles(accountObj)

	// 渲染结果到模板
	data := make(map[string]interface{})
	data["accountInfo"] = formatAccount(accountObj)
	data["account_roles"] = accountRoles
	data["loginAdminInfo"] = loginAdminInfo
	data["env_desc"] = utils.GetEnvDesc()

	return c.Render(http.StatusOK, "update_account_roles.html", data)
}

func DoUpdateAccountRole(c echo.Context) error {
	dataid := c.FormValue("id")
	if dataid == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要操作的账号"})
	}

	roleids := strings.TrimSpace(c.FormValue("roleids"))

	roleidsArray := make([]string, 0)
	if roleids != "" {
		roleidsArray = strings.Split(roleids, ",")
	}

	account := make(map[string]interface{})
	account["roles"] = roleidsArray
	account["update_time"] = time.Now().Unix()

	_, err := manager.UpdateAccount(dataid, account)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// DoDeleteAccount
func DoDeleteAccount(c echo.Context) error {
	dataid := c.FormValue("id")

	if dataid == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要删除的账号"})
	}

	// 判断账号是否存在
	accountObj, err := manager.GetAccountById(dataid)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
	}
	if accountObj.Id.Hex() != dataid {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
	}

	// 物理删除账号
	b, err := manager.DeleteAccount(dataid)
	if b == false {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// DoDeleteAccountBatch
func DoDeleteAccountBatch(c echo.Context) error {
	dataids := c.FormValue("ids")

	if dataids == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要删除的账号"})
	}

	dataidsArray := strings.Split(dataids, ",")

	for _, dataid := range dataidsArray {
		// 判断账号是否存在
		accountObj, err := manager.GetAccountById(dataid)
		if err != nil {
			return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
		}
		if accountObj.Id.Hex() != dataid {
			return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
		}

		// 物理删除账号
		b, err := manager.DeleteAccount(dataid)
		if b == false {
			return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
		}
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// DoSearchToken
func DoSearchToken(c echo.Context) error {
	accountId := c.FormValue("id")

	if accountId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要查询的账号"})
	}

	// 判断账号是否存在
	accountObj, err := manager.GetAccountById(accountId)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
	}
	if accountObj.Id.Hex() != accountId {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
	}

	// 查询账号Token
	token, err := manager.GetTokenByAccountId(accountId)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	data := make(map[string]interface{})
	data["token"] = token
	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功", Data: data})
}

// AccountList
func AccountList(c echo.Context) error {
	loginAdminInfo := manager.GetLoginAdminInfo(&c)

	id := c.QueryParam("id")
	name := c.QueryParam("name")
	account := c.QueryParam("account")

	skip, page := utils.GetSkipPage(utils.PageCount, c)

	// 查询模板列表
	count, _ := manager.GetAccountCount(id, name, account)
	roles, _ := manager.GetAccountList(id, name, account, skip, utils.PageCount)

	var accountList []map[string]interface{}
	for _, row := range roles {
		item := formatAccount(row)
		accountList = append(accountList, item)
	}

	res := utils.Paginator(page, utils.PageCount, count)

	linkPrefix, query := getAccountLinkPrefixQuery("/accountList?", id, name, account)

	// 渲染结果到模板
	data := make(map[string]interface{})
	data["accountList"] = accountList
	data["paginator"] = res
	data["linkPrefix"] = linkPrefix
	data["total"] = count
	data["loginAdminInfo"] = loginAdminInfo
	data["query"] = query
	data["env_desc"] = utils.GetEnvDesc()
	return c.Render(http.StatusOK, "account_list.html", data)
}

func formatAccount(row model.Account) map[string]interface{} {
	item := make(map[string]interface{})

	// 取创建人姓名
	admin, _, _ := manager.GetAdminById(row.Adminid)
	adminName := ""
	if admin.Id.Hex() != "" {
		adminName = admin.Name
	}

	photo := row.Photo
	if photo == "" {
		photo = "http://passport-bp.qschou.com/images/photos/default_avatar.jpg"
	}

	// 业务线
	businessLines := make([]map[string]interface{}, 0)
	for _, bs := range model.BusinessList {
		isSelect := false
		for _, bsKey := range row.BusinessLines {
			if bs["key"] == bsKey {
				isSelect = true
				break
			}
		}

		item := make(map[string]interface{})
		item["is_select"] = false
		if isSelect {
			item["is_select"] = true
		}
		item["key"] = bs["key"]
		item["name"] = bs["name"]

		businessLines = append(businessLines, item)
	}

	item["id"] = row.Id.Hex()
	item["name"] = row.Name
	item["account"] = row.Account
	item["photo"] = photo
	item["roles"] = row.Roles
	item["is_super"] = row.Is_Super
	item["department"] = row.Department
	item["department_desc"] = manager.DepartmentDesc[row.Department]
	item["business_lines"] = businessLines
	item["status"] = row.Status
	item["adminid"] = row.Adminid
	item["admin_name"] = adminName
	item["create_date"] = time.Unix(row.Create_time, 0).Format("2006-01-02 15:04:05")
	item["update_date"] = time.Unix(row.Update_time, 0).Format("2006-01-02 15:04:05")
	return item
}

func getAccountLinkPrefixQuery(linkPrefix string, id string, name string, account string) (string, map[string]interface{}) {
	query := make(map[string]interface{})
	if id != "" {
		query["id"] = id
		linkPrefix += fmt.Sprintf("id=%s&", id)
	}
	if name != "" {
		query["name"] = name
		linkPrefix += fmt.Sprintf("name=%s&", name)
	}
	if account != "" {
		query["account"] = account
		linkPrefix += fmt.Sprintf("account=%s&", account)
	}

	return linkPrefix, query
}

func getApps(account model.Account) []map[string]interface{} {
	accountApps := account.Apps

	apps, _ := manager.GetAllAppList()
	plen := len(apps)
	var appList = make([]map[string]interface{}, plen)
	index := 0
	for _, app := range apps {
		item := make(map[string]interface{})
		item["id"] = app.Id.Hex()
		item["name"] = app.App_name
		item["is_select"] = false
		for _, aid := range accountApps {
			if aid == app.Id.Hex() {
				item["is_select"] = true
			}
		}
		appList[index] = item
		index++
	}

	return appList
}

func getRoles(account model.Account) []map[string]interface{} {
	accountRoles := account.Roles

	roles, _ := manager.GetAllRoles()
	plen := len(roles)
	var roleList = make([]map[string]interface{}, plen)
	index := 0
	for _, role := range roles {
		item := make(map[string]interface{})
		item["id"] = role.Id.Hex()
		item["name"] = role.Name
		item["is_select"] = false
		for _, rid := range accountRoles {
			if rid == role.Id.Hex() {
				item["is_select"] = true
			}
		}
		roleList[index] = item
		index++
	}

	return roleList
}
